using System.Text;
using Admin.Domain.Config;
using Admin.Domain.Entities;
using Admin.Domain.Events;
using Admin.Domain.IEvents;
using Admin.Domain.Repositories;
using Admin.Infrastructure.Date;
using Admin.Infrastructure.Events;
using Admin.Infrastructure.Repositories;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

namespace Admin.Infrastructure;

public static class ServiceCollectionExtension
{
    public static IServiceCollection AddAdminInfrastructure(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddDbContext<AdminDbContext>(options =>
        {
            options.UseNpgsql(configuration.GetConnectionString("pgsql"))
                   .UseLazyLoadingProxies();
        });

        services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>));
        services.AddScoped<ITokenService, JwtTokenService>();
        services.AddScoped<ISystemLogRepository, SystemLogRepository>();
        services.AddScoped<IEventHandler<UserCreatedEvent>,UserCreatedEventHandler>();
        services.AddScoped(typeof(IEventPublisher),typeof(EventPublisher));
        services.Configure<JwtConfig>(configuration.GetSection("JwtConfig"));

        AddJwtAuthentication(services, configuration);

        return services;
    }

    private static void AddJwtAuthentication(IServiceCollection services, IConfiguration configuration)
    {
        var jwtConfig = configuration.GetSection("JwtConfig").Get<JwtConfig>();

        if (jwtConfig == null || string.IsNullOrEmpty(jwtConfig.Secret))
        {
            SystemLog.Create("JWT 配置缺失或无效，请检查 appsettings.json 中的 JwtConfig 节点。");
            return;
        }

        var key = Encoding.ASCII.GetBytes(jwtConfig.Secret);

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero
            };
        });
    }
}